package com.trendit.openapi.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.trendit.openapi.result.ResponseResult;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;

public class DaQuRequestUtils {

    private static final ObjectMapper objectMapper;
    private static final RestTemplate restTemplate;


    static {
        // Init object mapper
        objectMapper = new ObjectMapper();
        // 设置输出时包含属性的风格
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(LocalDateTimeUtils.DATE_TIME_FORMAT_PATTERN)));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(LocalDateTimeUtils.DATE_FORMAT_PATTERN)));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(LocalDateTimeUtils.TIME_FORMAT_PATTERN)));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(LocalDateTimeUtils.DATE_TIME_FORMAT_PATTERN)));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(LocalDateTimeUtils.DATE_FORMAT_PATTERN)));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(LocalDateTimeUtils.TIME_FORMAT_PATTERN)));
        objectMapper.registerModule(javaTimeModule);
        // RestTemplate init
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        // 设置超时时间
        factory.setConnectTimeout(3000);
        factory.setReadTimeout(5000);
        restTemplate = new RestTemplate(factory);
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        for (int i = 0; i < messageConverters.size(); i++) {
            HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
            if (httpMessageConverter instanceof StringHttpMessageConverter) {
                messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            } else if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) {
                messageConverters.set(i, new MappingJackson2HttpMessageConverter(objectMapper));
            }
        }
    }

    /**
     * 发起请求
     *
     * @param url           url
     * @param body          请求body对象
     * @param typeReference 响应类型
     */
    public static <R, P> ResponseResult<R> post(String url, P body, ParameterizedTypeReference<ResponseResult<R>> typeReference) {
        try {
            String requestBodyStr = objectMapper.writeValueAsString(body);
            HttpHeaders hexSignHeader = getHeader(requestBodyStr);
            hexSignHeader.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> request = new HttpEntity<>(requestBodyStr, hexSignHeader);
            return restTemplate.exchange(url, HttpMethod.POST, request, typeReference).getBody();
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 设备请求头
     */
    public static HttpHeaders getHeader(String requestBodyStr) {
        String appId = "your appid";
        String appSecret = "your appSecret";
        long stime = ZonedDateTime.now().toEpochSecond();
        String uid = UUID.randomUUID().toString();

        String originContext = uid + appId + stime + appSecret;
        if (requestBodyStr != null) {
            originContext += requestBodyStr;
        }

        HttpHeaders headers = new HttpHeaders();
        String sign = DigestUtils.md5Hex(originContext);
        headers.add("appid", appId);
        headers.add("uid", uid);
        headers.add("stime", String.valueOf(stime));
        headers.add("sign", sign);
        return headers;
    }

}
